
package eg.ci.mvn.service.demo.controller;

import cn.hutool.core.collection.CollUtil;
import eg.ci.mvn.service.api.constant.*;
import eg.ci.mvn.service.api.model.BaseResponse;
import eg.ci.mvn.service.api.model.ErrorType;
import eg.ci.mvn.service.api.model.dto.ParkingCar;
import eg.ci.mvn.service.api.model.param.ParkingGlobalParam;
import eg.ci.mvn.service.api.model.param.ParkingParam;
import eg.ci.mvn.service.demo.facade.AccessCtrlServiceFacade;
import eg.ci.mvn.service.demo.facade.CardServiceFacade;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static eg.ci.mvn.service.api.model.param.ParkingCardParam.CardGroup;
import static eg.ci.mvn.service.api.model.param.ParkingMemberParam.CardMember;
import static eg.ci.mvn.service.api.model.param.ParkingParam.ParkingSignalParam;

/**
 * 停车业务实例
 */
@Slf4j
@RestController
@RequestMapping(value = "demo/parking")
@Tag(name = ApiNo.DEMO_PARKING)
public class ParkingController {
    /**
     * 待入车清单 通道口 车信息
     */
    private Map<String, ParkingCar> parkingPrepareCarMap = new HashMap<>();

    /**
     * 禁入车清单
     */
    private List<ParkingCar> parkingForbiddenCarList = new ArrayList<>();

    //
    /**
     * 已出场车清单
     */
    private List<ParkingCar> parkingLeaveCarList = new ArrayList<>();

    /**
     * 在场车清单
     */
    private Map<String, ParkingCar> parkingCarMap = new HashMap<>();

    @Resource
    private CardServiceFacade cardServiceFacade;

    @Resource
    private AccessCtrlServiceFacade ruleServiceFacade;

    /**
     * 闸道信号识别, 传入车主车辆信息
     *
     * @param request
     * @return
     */
    @Operation(summary = ApiNo.DEMO_PARKING_SIGNAL, description = ApiNo.DEMO_PARKING_SIGNAL)
    @PostMapping(value = "signal")
    public BaseResponse<ParkingCar> signal(@RequestBody ParkingSignalParam request) {
        log.info("{}", request);

        // 进出场判断识别
        boolean inFlag = !parkingCarMap.containsKey(request.getCarPlateNo());
        log.info("{} {}", request.getCarPlateNo(), inFlag ? "正在进场" : "正在离场");

        ParkingCar parkingCar = null;

        if (inFlag) {
            CardGroup tempCard = cardServiceFacade.tempCardGroup(request.getGateNo());
            Assert.notNull(tempCard, "区域未开放临停 ");

            // 1. 判定会员 车辆卡证信息     卡证(不同类型优先级 黑名单 > 临停 > 白名单 > 月卡)
            CardMember cardMember = cardServiceFacade.carMember(request.getGateNo(), request.getCarPlateNo(), request.getCarPlateColor());

            // 2. 判定卡证 临停卡证或会员卡证
            CardGroup card = cardMember != null ? cardServiceFacade.cardGroup(cardMember.getCardGroupId()) : tempCard;

            // 3. 判定通行类型             标志 0-无限制 1-禁止通过 2-允许通过 3-弹框确认
            Integer accessRuleType = ruleServiceFacade.access(CollUtil.newArrayList(card), request);

            // 4. 构建停车对象
            parkingCar = ParkingCar.builder()
                    .carPlateNo(request.getCarPlateNo())
                    .carPlateColor(request.getCarPlateColor())
                    .cardGroup(card)
                    .cardMember(cardMember)
                    .inGateCode(request.getGateNo())
                    .outGateCode(null)
                    .inTime(Long.valueOf(request.getTime()))
                    .outTime(0L)
                    .inPhoto(null)
                    .outPhoto(null)
                    .inOutState(InOutStateEnum.PREPARE_ENTER.itemValue())
                    .cardClassify(String.valueOf(card.getClassify()))
                    .accessRuleType(String.valueOf(accessRuleType))
                    .chargeType(ChargeTypeEnum.NON_PAY.itemValue())
                    .reducingType(ReducingTypeEnum.NON_REDUCING.itemValue())
                    .exceptionType(String.valueOf(0))
                    .build();

            // TODO 进场记录保存
            log.info("{} {}", request.getCarPlateNo(), "进场车 数据打点和保存");

            if ("3".equals(parkingCar.getAccessRuleType())) {
                parkingPrepareCarMap.put(request.getGateNo(), parkingCar);
            } else if ("1".equals(parkingCar.getAccessRuleType())) {
                parkingForbiddenCarList.add(parkingCar);
            } else if ("0".equals(parkingCar.getAccessRuleType()) || "2".equals(parkingCar.getAccessRuleType())) {
                parkingCarMap.put(request.getCarPlateNo(), parkingCar);
            }

        } else {
            // TODO 锁定当前离场时间5分钟, 进行计费
            // TODO 如果应收费大于 0 , 刷新车辆应收费用
            // TODO 如果应收费用 = ( 已缴金额 + 优惠金额 + 实收金额 ) , 离场抬杆
            parkingCar = parkingCarMap.remove(request.getCarPlateNo());
            parkingLeaveCarList.add(parkingCar);
        }
        log.info("{} {}", request.getCarPlateNo(), parkingCar);

        return new BaseResponse<>(parkingCar, ErrorType.SUCCESS);
    }

    /**
     * 传入车主主动或者被动扣款信息
     *
     * @param request
     * @return
     */
    @Operation(summary = ApiNo.DEMO_PARKING_PAY, description = ApiNo.DEMO_PARKING_PAY)
    @PostMapping(value = "pay")
    public BaseResponse pay(@RequestBody ParkingParam.ParkingPayParam request) {
        log.info("{}", request);
        return new BaseResponse<>(ErrorType.SUCCESS);
    }


    /**
     * 查询道闸口车牌信息
     *
     * @param request
     * @return
     */
    @Operation(summary = ApiNo.DEMO_PARKING_GATE, description = ApiNo.DEMO_PARKING_GATE)
    @PostMapping(value = "gate")
    public BaseResponse gate(@RequestBody ParkingParam.ParkingQueryGateParam request) {
        log.info("{}", request);
        return new BaseResponse<>(ErrorType.SUCCESS);
    }

    /**
     * 查询车辆信息
     *
     * @param request
     * @return
     */
    @Operation(summary = ApiNo.DEMO_PARKING_CAR, description = ApiNo.DEMO_PARKING_CAR)
    @PostMapping(value = "car")
    public BaseResponse car(@RequestBody ParkingParam.ParkingQueryCarParam request) {
        log.info("{}", request);
        return new BaseResponse<>(ErrorType.SUCCESS);
    }

    /**
     * 查询停车场全局信息
     *
     * @param request
     * @return
     */
    @Operation(summary = ApiNo.DEMO_PARKING_GLOBAL, description = ApiNo.DEMO_PARKING_GLOBAL)
    @PostMapping(value = "global")
    public BaseResponse global(@RequestBody ParkingGlobalParam.ParkingQueryGlobalParam request) {
        log.info("{}", request);
        if (DemoConstant.GLOBAL.getParkCode().equals(request.getParkCode())) {
            return new BaseResponse<>(DemoConstant.GLOBAL, ErrorType.SUCCESS);
        } else {
            ParkingGlobalParam.ParkingQueryGlobalParam response = new ParkingGlobalParam.ParkingQueryGlobalParam();
            response.setParkCode(request.getParkCode());
            return new BaseResponse<>(response, ErrorType.SUCCESS);
        }
    }
}
